package com.example.workflow.service.impl;

import com.example.workflow.dto.OrderStatusCountDto;
import com.example.workflow.dto.OrderTimeSeriesDto;
import com.example.workflow.dto.OrderTypeCountDto;
import com.example.workflow.mapper.UserOrderStatsMapper;
import com.example.workflow.service.UserOrderStatsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.time.DayOfWeek;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 用户工单统计服务实现类
 */
@Service
@Slf4j
public class UserOrderStatsServiceImpl implements UserOrderStatsService {

    @Autowired
    private UserOrderStatsMapper userOrderStatsMapper;

    /**
     * 根据时间间隔生成完整的日期序列
     * @param begin 开始日期
     * @param end 结束日期
     * @param gap 时间间隔 (day/week/month)
     * @return 完整的日期序列
     */
    private List<LocalDate> generateDateRange(LocalDate begin, LocalDate end, String gap) {
        log.info("生成日期序列: 开始={}, 结束={}, 间隔={}", begin, end, gap);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<LocalDate> result;
        
        switch (gap) {
            case "day":
                // 按天生成日期序列
                result = Stream.iterate(begin, date -> date.plusDays(1))
                    .limit(ChronoUnit.DAYS.between(begin, end) + 1)
                    .collect(Collectors.toList());
                log.info("按天生成序列，共{}天", result.size());
                return result;
                
            case "week":
                // 按周生成日期序列，确保周一为每周第一天
                log.info("开始计算周序列，开始日期={}，结束日期={}", begin, end);
                
                // 找到包含开始日期的那周的周一
                LocalDate firstMonday = begin.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
                log.info("计算得到的第一个周一: {}", firstMonday);
                
                // 找到包含结束日期的那周的周一
                LocalDate lastWeekMonday = end.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
                log.info("计算得到的最后一周的周一: {}", lastWeekMonday);
                
                // 计算周数
                long weekCount = ChronoUnit.WEEKS.between(firstMonday, lastWeekMonday) + 1;
                log.info("计算得到的总周数: {}", weekCount);
                
                // 生成所有周一的列表
                result = Stream.iterate(firstMonday, date -> date.plusWeeks(1))
                    .limit(weekCount)
                    .collect(Collectors.toList());
                
                log.info("周计算最终结果: 从{}开始，共{}个周，周列表={}",
                    firstMonday, result.size(),
                    result.stream().map(formatter::format).collect(Collectors.joining(", ")));
                return result;
                
            case "month":
                // 按月生成日期序列
                LocalDate firstDayOfMonth = begin.withDayOfMonth(1);
                long monthCount = ChronoUnit.MONTHS.between(firstDayOfMonth, end) + 1;
                
                result = Stream.iterate(firstDayOfMonth, date -> date.plusMonths(1))
                    .limit(monthCount)
                    .collect(Collectors.toList());
                log.info("按月生成序列，从{}开始，共{}个月", firstDayOfMonth, result.size());
                return result;
                
            default:
                throw new IllegalArgumentException("不支持的时间间隔类型: " + gap);
        }
    }

    /**
     * 获取指定日期范围内工单计数统计，以时序数组形式返回
     * URL: /user/order/count
     *
     * @param userId 用户ID
     * @param begin 开始日期
     * @param end 结束日期
     * @param gap 时间间隔 (day/week/month)
     * @return 时序格式的工单统计数据
     */
    @Override
    public OrderTimeSeriesDto countOrdersByTimeRange(Integer userId, LocalDate begin, LocalDate end, String gap) {
        log.info("获取用户{}从{}到{}的工单时序统计，间隔为{}", userId, begin, end, gap);
        
        // 获取原始统计数据
        List<Map<String, Object>> statsData;
        
        // 根据时间间隔选择不同的统计方法
        switch (gap.toLowerCase()) {
            case "day":
                statsData = userOrderStatsMapper.countOrdersByDay(userId, begin, end);
                break;
            case "week":
                statsData = userOrderStatsMapper.countOrdersByWeek(userId, begin, end);
                break;
            case "month":
                statsData = userOrderStatsMapper.countOrdersByMonth(userId, begin, end);
                break;
            default:
                log.error("不支持的时间间隔类型: {}", gap);
                throw new IllegalArgumentException("不支持的时间间隔类型: " + gap);
        }
        
        log.info("从数据库获取的原始统计数据: {}", statsData);
        
        // 创建日期-计数映射，便于快速查询
        Map<String, Integer> dateCountMap = new HashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        
        for (Map<String, Object> data : statsData) {
            String dateStr = data.get("date").toString();
            if (dateStr.length() >= 10) {
                dateStr = dateStr.substring(0, 10); // 确保只取 yyyy-MM-dd 部分
            }
            int count = Integer.parseInt(data.get("count").toString());
            dateCountMap.put(dateStr, count);
            log.info("原始数据: 日期 = {}, 计数 = {}", dateStr, count);
        }
        
        // 根据间隔生成完整的日期序列
        List<LocalDate> dateList = generateDateRange(begin, end, gap.toLowerCase());
        log.info("生成的日期序列: {}", dateList.stream().map(formatter::format).collect(Collectors.toList()));
        
        // 创建结果对象
        OrderTimeSeriesDto result = new OrderTimeSeriesDto();
        List<String> timeList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();
        
        // 填充数据
        for (LocalDate date : dateList) {
            String dateStr = date.format(formatter);
            timeList.add(dateStr);
            int count = dateCountMap.getOrDefault(dateStr, 0);
            countList.add(count);
            log.info("最终数据: 日期 = {}, 计数 = {}", dateStr, count);
        }
        
        result.setTime(timeList);
        result.setCount(countList);
        
        log.info("时序统计结果: 共{}个时间点", timeList.size());
        return result;
    }

    /**
     * 获取用户各个状态工单的数量统计
     * URL: /user/order/status-count
     *
     * @param userId 用户ID
     * @return 各状态工单数量统计
     */
    @Override
    public OrderStatusCountDto countUserOrdersByStatus(Integer userId) {
        log.info("开始统计用户{}的各状态工单数量", userId);
        
        Map<String, Object> statsData = userOrderStatsMapper.countUserOrdersByStatus(userId);
        if (statsData == null) {
            log.warn("未找到用户{}的工单类型统计数据，返回空结果", userId);
            statsData = new HashMap<>(); // 创建空Map而不是直接使用null
        }
        log.info("查询到的工单状态统计数据: {}", statsData);
        
        // 创建并填充结果对象
        OrderStatusCountDto result = new OrderStatusCountDto();
        
        // 设置各状态数量，处理BigDecimal到Integer的转换
        result.setApproved(convertToInteger(statsData.get("approved")));
        result.setCompleted(convertToInteger(statsData.get("completed")));
        result.setDispatched(convertToInteger(statsData.get("dispatched")));
        result.setDraft(convertToInteger(statsData.get("draft")));
        result.setOperating(convertToInteger(statsData.get("operating")));
        result.setPending_l1(convertToInteger(statsData.get("pending_l1")));
        result.setPending_l2(convertToInteger(statsData.get("pending_l2")));
        result.setProcessing(convertToInteger(statsData.get("processing")));
        result.setRejected(convertToInteger(statsData.get("rejected")));
        result.setTotal(convertToInteger(statsData.get("total")));
        
        log.info("用户{}的工单状态统计结果: {}", userId, result);
        return result;
    }
    
    /**
     * 将Object值安全转换为Integer
     * 处理BigDecimal、Integer、Long等类型
     */
    private Integer convertToInteger(Object value) {
        if (value == null) {
            return 0;
        }
        
        if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof BigDecimal) {
            return ((BigDecimal) value).intValue();
        } else if (value instanceof Long) {
            return ((Long) value).intValue();
        } else {
            try {
                return Integer.parseInt(value.toString());
            } catch (NumberFormatException e) {
                log.warn("无法将 {} 转换为Integer，使用默认值0", value);
                return 0;
            }
        }
    }

    @Override
    public OrderTypeCountDto countUserOrdersByType(Integer userId) {
        log.info("开始统计用户{}的各类型工单数量", userId);
        
        Map<String, Object> statsData = userOrderStatsMapper.countUserOrdersByType(userId);
        log.info("查询到的工单类型统计数据: {}", statsData);
        
        // 创建并填充结果对象
        OrderTypeCountDto result = new OrderTypeCountDto();
        
        // 设置各类型数量，处理BigDecimal到Integer的转换
        result.setFaultRepair(convertToInteger(statsData.get("fault_repair")));
        result.setDemandRequest(convertToInteger(statsData.get("demand_request")));
        result.setRoutineMaintenance(convertToInteger(statsData.get("routine_maintenance")));
        result.setOtherService(convertToInteger(statsData.get("other_service")));
        
        log.info("用户{}的工单类型统计结果: {}", userId, result);
        return result;
    }
} 